Shiny

Shiny is an R package that makes it easy to build interactive web apps straight from R. You can host standalone apps on a webpage or embed them in R Markdown documents or build dashboards. You can also extend your Shiny apps with CSS themes, htmlwidgets, and JavaScript actions.

Shiny is most often used with the packages “shinydashboard” or “flexdashboard” to build interactive dashboards. We will walk through how to use both shinydashboard and flexdashboard to give you options when using shiny.

Shiny dashboard structure (UI - user interface)

3 Main parts:

  • Header - dashboardHeader()
  • Sidebar - dashboardSidebar()
  • Body - dashboardBody()

How to build a Sidebar Dashboard

library(shinydashboard)

sidebar <- dashboardSidebar(
  sidebarMenu(
    menuItem("Data",
      tabName = "data") #Used for linking in the body
  )
)

If you want more interactivity on your dashboard, shiny has some functions that enables you to do that. You can use a number of different input options using shiny. This allows the user of the website to input information - whether it’s text, a date, or to select options from data that you provide.

Different input functions: * selectInput() # Allows user to select a singular item from a list * textInput() # Allows user to input text * dateInput() # Allows user to input a date * checkboxInput()

How to build user input with shinydashboard

library("shiny")
library("tidyverse")

selectInput(
  inputId = "object", # This is the name you described the object elsewhere in the application
  label = "Favorite Character", # The label you want to show to the user
  choices = c(starwars$name) # List the choices the user has to pick from
 )

Render Functions

Functions that you use in your application’s server side code, assigning them to outputs that appear in your user interface.

  • renderPrint()
  • renderText()
  • renderPlot()
  • renderUI() # HTML or a shiny tag object

Example Using Star Wars df

header <- dashboardHeader(
  title = "Example Dashboard Header",
  color = 'green'
)
[1] "green"
Error in FUN(X[[i]], ...) : Expected an object with class 'shiny.tag'.

After you code the sidebar and body, you can then create the User Interface, or “ui”. The User Interface is built from a header, sidebar, and body. When you modify any of these options, the easiest way is to save it as an object called “header”, “sidebar”, or “body”. The user interface is most often coded into the dashboardPage() function.

ui <- dashboardPage(header = header,
                    sidebar = sidebar,
                    body = body
                    )

server <- function(input, output) {
  output$name <- renderText({
      input$name
    })
}

shinyApp(ui, server)

Shinydashboard Layout

There are two main types of layouts that shiny uses. The first is a “row” based layout, while the other is a “column” based layout. You can use either one, or even a mix of the two. The way to create the layouts is by using the “fluidRow()” function.

These functions are used inside of the dashboardBody() section. Each time “fluidRow()” is called, a new row is created.

Row layout

body <- dashboardBody(
  fluidRow(
# Row 1
  box(
  width = 12, # 12 width spans the entire width of the screen
  title = "Regular Box, Row 1",
  "Text inside of box"
  )),
  fluidRow(
# Row 2
  box(
  width = 12,
  title = "Regular Box, Row 2",
  "Text inside of box 2"
  )
)
)
ui <- dashboardPage(header = dashboardHeader(),
                    sidebar = dashboardSidebar(),
                    body = body
                    )

ui

Column Layout

body <- dashboardBody(
    fluidRow(
    #   Column 1
      column(width = 6,
      infoBox(
        width = NULL, # The width must be "NULL" when using a column layout
        title = "Regular Box, Column 1",
        "Text inside of box"
         )      
   ),
  column(width = 6,
    #   Column 2
      infoBox(
        width = NULL, # The width must be "NULL" when using a column layout
        title = "Regular Box, Column 2",
        "Text inside of box"
         )      
   )
)
)
ui <- dashboardPage(header = dashboardHeader(),
                    sidebar = dashboardSidebar(),
                    body = body
                    )

shinyApp(ui, server)

Mix of Column and Row Layout

Note: To create a new row, you call another fluidRow() function.

body <- dashboardBody(
    fluidRow(
    #   Row 1
      box(
        width = 12, # The width must be "NULL" when using a column layout
        title = "Regular Box, Row 1",
        "Text inside of box"
         ),
    ),
  fluidRow(
    column(width = 6,
    #   Column 2
      infoBox(
        width = NULL, # The width must be "NULL" when using a column layout
        title = "Regular Box, Row 2, Column 1",
        subtitle = "Text inside of box"
         )
    ),
    column(width = 6,
      infoBox(
        width = NULL,
        title = "Regular Box, Row 2, Column 2",
        subtitle = "Text inside of box"
      )
    )
  )
)

ui <- dashboardPage(header = dashboardHeader(),
                    sidebar = dashboardSidebar(),
                    body = body
                    )

shinyApp(ui, server)

Flexdashboard

Flexdashboard is a similar dashboard system as shiny. A flexdashboard is filled with charts. To create a flexdashboard, you will first need to adjust the YAML header.

title: “title of document” output: flexdashboard::flex_dashboard

Now your Rmarkdown file will be interpreted as a flexdashboard file.

The flexdashboard default layout is in columns. To separate the columns, you will use the following syntax:

library(flexdashboard)

Column

Chart A

Column

Chart B

Chart C

LS0tDQp0aXRsZTogIlNoaW55IFdhbGt0aHJvdWdoIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyBTaGlueQ0KDQpTaGlueSBpcyBhbiBSIHBhY2thZ2UgdGhhdCBtYWtlcyBpdCBlYXN5IHRvIGJ1aWxkIGludGVyYWN0aXZlIHdlYiBhcHBzIHN0cmFpZ2h0IGZyb20gUi4gWW91IGNhbiBob3N0IHN0YW5kYWxvbmUgYXBwcyBvbiBhIHdlYnBhZ2Ugb3IgZW1iZWQgdGhlbSBpbiBSIE1hcmtkb3duIGRvY3VtZW50cyBvciBidWlsZCBkYXNoYm9hcmRzLiBZb3UgY2FuIGFsc28gZXh0ZW5kIHlvdXIgU2hpbnkgYXBwcyB3aXRoIENTUyB0aGVtZXMsIGh0bWx3aWRnZXRzLCBhbmQgSmF2YVNjcmlwdCBhY3Rpb25zLg0KDQpTaGlueSBpcyBtb3N0IG9mdGVuIHVzZWQgd2l0aCB0aGUgcGFja2FnZXMgInNoaW55ZGFzaGJvYXJkIiBvciAiZmxleGRhc2hib2FyZCIgdG8gYnVpbGQgaW50ZXJhY3RpdmUgZGFzaGJvYXJkcy4gV2Ugd2lsbCB3YWxrIHRocm91Z2ggaG93IHRvIHVzZSBib3RoIHNoaW55ZGFzaGJvYXJkIGFuZCBmbGV4ZGFzaGJvYXJkIHRvIGdpdmUgeW91IG9wdGlvbnMgd2hlbiB1c2luZyBzaGlueS4NCg0KDQojIyBTaGlueSBkYXNoYm9hcmQgc3RydWN0dXJlIChVSSAtIHVzZXIgaW50ZXJmYWNlKQ0KDQozIE1haW4gcGFydHM6DQoNCiogSGVhZGVyIC0gZGFzaGJvYXJkSGVhZGVyKCkNCiogU2lkZWJhciAtIGRhc2hib2FyZFNpZGViYXIoKQ0KKiBCb2R5IC0gZGFzaGJvYXJkQm9keSgpDQoNCg0KIyMjIEhvdyB0byBidWlsZCBhIFNpZGViYXIgRGFzaGJvYXJkDQoNCmBgYHtyfQ0KbGlicmFyeShzaGlueWRhc2hib2FyZCkNCg0Kc2lkZWJhciA8LSBkYXNoYm9hcmRTaWRlYmFyKA0KICBzaWRlYmFyTWVudSgNCiAgICBtZW51SXRlbSgiRGF0YSIsDQogICAgICB0YWJOYW1lID0gImRhdGEiKSAjVXNlZCBmb3IgbGlua2luZyBpbiB0aGUgYm9keQ0KICApDQopDQpgYGANCg0KSWYgeW91IHdhbnQgbW9yZSBpbnRlcmFjdGl2aXR5IG9uIHlvdXIgZGFzaGJvYXJkLCBzaGlueSBoYXMgc29tZSBmdW5jdGlvbnMgdGhhdCBlbmFibGVzIHlvdSB0byBkbyB0aGF0LiBZb3UgY2FuIHVzZSBhIG51bWJlciBvZiBkaWZmZXJlbnQgaW5wdXQgb3B0aW9ucyB1c2luZyBzaGlueS4gVGhpcyBhbGxvd3MgdGhlIHVzZXIgb2YgdGhlIHdlYnNpdGUgdG8gaW5wdXQgaW5mb3JtYXRpb24gLSB3aGV0aGVyIGl0J3MgdGV4dCwgYSBkYXRlLCBvciB0byBzZWxlY3Qgb3B0aW9ucyBmcm9tIGRhdGEgdGhhdCB5b3UgcHJvdmlkZS4NCg0KRGlmZmVyZW50IGlucHV0IGZ1bmN0aW9uczoNCiogc2VsZWN0SW5wdXQoKSAjIEFsbG93cyB1c2VyIHRvIHNlbGVjdCBhIHNpbmd1bGFyIGl0ZW0gZnJvbSBhIGxpc3QNCiogdGV4dElucHV0KCkgIyBBbGxvd3MgdXNlciB0byBpbnB1dCB0ZXh0DQoqIGRhdGVJbnB1dCgpICMgQWxsb3dzIHVzZXIgdG8gaW5wdXQgYSBkYXRlDQoqIGNoZWNrYm94SW5wdXQoKQ0KDQoNCiMjIyBIb3cgdG8gYnVpbGQgdXNlciBpbnB1dCB3aXRoIHNoaW55ZGFzaGJvYXJkDQoNCmBgYHtyfQ0KbGlicmFyeSgic2hpbnkiKQ0KbGlicmFyeSgidGlkeXZlcnNlIikNCg0Kc2VsZWN0SW5wdXQoDQogIGlucHV0SWQgPSAib2JqZWN0IiwgIyBUaGlzIGlzIHRoZSBuYW1lIHlvdSBkZXNjcmliZWQgdGhlIG9iamVjdCBlbHNld2hlcmUgaW4gdGhlIGFwcGxpY2F0aW9uDQogIGxhYmVsID0gIkZhdm9yaXRlIENoYXJhY3RlciIsICMgVGhlIGxhYmVsIHlvdSB3YW50IHRvIHNob3cgdG8gdGhlIHVzZXINCiAgY2hvaWNlcyA9IGMoc3RhcndhcnMkbmFtZSkgIyBMaXN0IHRoZSBjaG9pY2VzIHRoZSB1c2VyIGhhcyB0byBwaWNrIGZyb20NCiApDQpgYGANCg0KDQojIyMgUmVuZGVyIEZ1bmN0aW9ucyANCkZ1bmN0aW9ucyB0aGF0IHlvdSB1c2UgaW4geW91ciBhcHBsaWNhdGlvbidzIHNlcnZlciBzaWRlIGNvZGUsIGFzc2lnbmluZyB0aGVtIHRvIG91dHB1dHMgdGhhdCBhcHBlYXIgaW4geW91ciB1c2VyIGludGVyZmFjZS4NCg0KKiByZW5kZXJQcmludCgpDQoqIHJlbmRlclRleHQoKQ0KKiByZW5kZXJQbG90KCkNCiogcmVuZGVyVUkoKSAjIEhUTUwgb3IgYSBzaGlueSB0YWcgb2JqZWN0DQoNCiMjIEV4YW1wbGUgVXNpbmcgU3RhciBXYXJzIGRmDQpgYGB7cn0NCmxpYnJhcnkoc2hpbnkpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoc2hpbnlkYXNoYm9hcmQpDQoNCmhlYWRlciA8LSBkYXNoYm9hcmRIZWFkZXIoDQogIHRpdGxlID0gIkV4YW1wbGUgRGFzaGJvYXJkIEhlYWRlciIsDQogIHRpdGxlV2lkdGggPSAzMDANCikNCg0Kc2lkZWJhciA8LSBkYXNoYm9hcmRTaWRlYmFyKA0KICBzZWxlY3RJbnB1dCgNCiAgICBpbnB1dElkID0gIm5hbWUiLA0KICAgIGxhYmVsID0gIkZhdm9yaXRlIENoYXJhY3RlciIsDQogICAgY2hvaWNlcyA9IGMoc3RhcndhcnMkbmFtZSkNCiAgKQ0KKQ0KDQpib2R5IDwtIGRhc2hib2FyZEJvZHkoDQogIHRleHRPdXRwdXQoIm5hbWUiKQ0KKQ0KYGBgDQoNCg0KQWZ0ZXIgeW91IGNvZGUgdGhlIHNpZGViYXIgYW5kIGJvZHksIHlvdSBjYW4gdGhlbiBjcmVhdGUgdGhlIFVzZXIgSW50ZXJmYWNlLCBvciAidWkiLiBUaGUgVXNlciBJbnRlcmZhY2UgaXMgYnVpbHQgZnJvbSBhIGhlYWRlciwgc2lkZWJhciwgYW5kIGJvZHkuIFdoZW4geW91IG1vZGlmeSBhbnkgb2YgdGhlc2Ugb3B0aW9ucywgdGhlIGVhc2llc3Qgd2F5IGlzIHRvIHNhdmUgaXQgYXMgYW4gb2JqZWN0IGNhbGxlZCAiaGVhZGVyIiwgInNpZGViYXIiLCBvciAiYm9keSIuIFRoZSB1c2VyIGludGVyZmFjZSBpcyBtb3N0IG9mdGVuIGNvZGVkIGludG8gdGhlIGRhc2hib2FyZFBhZ2UoKSBmdW5jdGlvbi4NCg0KDQpgYGB7cn0NCnVpIDwtIGRhc2hib2FyZFBhZ2UoaGVhZGVyID0gaGVhZGVyLA0KICAgICAgICAgICAgICAgICAgICBzaWRlYmFyID0gc2lkZWJhciwNCiAgICAgICAgICAgICAgICAgICAgYm9keSA9IGJvZHkNCiAgICAgICAgICAgICAgICAgICAgKQ0KDQpzZXJ2ZXIgPC0gZnVuY3Rpb24oaW5wdXQsIG91dHB1dCkgew0KICBvdXRwdXQkbmFtZSA8LSByZW5kZXJUZXh0KHsNCiAgICAgIGlucHV0JG5hbWUNCiAgICB9KQ0KfQ0KDQpzaGlueUFwcCh1aSwgc2VydmVyKQ0KDQpgYGANCg0KDQoNCiMjIFNoaW55ZGFzaGJvYXJkIExheW91dA0KDQpUaGVyZSBhcmUgdHdvIG1haW4gdHlwZXMgb2YgbGF5b3V0cyB0aGF0IHNoaW55IHVzZXMuIFRoZSBmaXJzdCBpcyBhICJyb3ciIGJhc2VkIGxheW91dCwgd2hpbGUgdGhlIG90aGVyIGlzIGEgImNvbHVtbiIgYmFzZWQgbGF5b3V0LiBZb3UgY2FuIHVzZSBlaXRoZXIgb25lLCBvciBldmVuIGEgbWl4IG9mIHRoZSB0d28uDQpUaGUgd2F5IHRvIGNyZWF0ZSB0aGUgbGF5b3V0cyBpcyBieSB1c2luZyB0aGUgImZsdWlkUm93KCkiIGZ1bmN0aW9uLiANCg0KVGhlc2UgZnVuY3Rpb25zIGFyZSB1c2VkIGluc2lkZSBvZiB0aGUgZGFzaGJvYXJkQm9keSgpIHNlY3Rpb24uIEVhY2ggdGltZSAiZmx1aWRSb3coKSIgaXMgY2FsbGVkLCBhIG5ldyByb3cgaXMgY3JlYXRlZC4gDQoNClJvdyBsYXlvdXQNCmBgYHtyfQ0KYm9keSA8LSBkYXNoYm9hcmRCb2R5KA0KICBmbHVpZFJvdygNCiMgUm93IDENCiAgYm94KA0KICB3aWR0aCA9IDEyLCAjIDEyIHdpZHRoIHNwYW5zIHRoZSBlbnRpcmUgd2lkdGggb2YgdGhlIHNjcmVlbg0KICB0aXRsZSA9ICJSZWd1bGFyIEJveCwgUm93IDEiLA0KICAiVGV4dCBpbnNpZGUgb2YgYm94Ig0KICApKSwNCiAgZmx1aWRSb3coDQojIFJvdyAyDQogIGJveCgNCiAgd2lkdGggPSAxMiwNCiAgdGl0bGUgPSAiUmVndWxhciBCb3gsIFJvdyAyIiwNCiAgIlRleHQgaW5zaWRlIG9mIGJveCAyIg0KICApDQopDQopDQp1aSA8LSBkYXNoYm9hcmRQYWdlKGhlYWRlciA9IGRhc2hib2FyZEhlYWRlcigpLA0KICAgICAgICAgICAgICAgICAgICBzaWRlYmFyID0gZGFzaGJvYXJkU2lkZWJhcigpLA0KICAgICAgICAgICAgICAgICAgICBib2R5ID0gYm9keQ0KICAgICAgICAgICAgICAgICAgICApDQoNCnVpDQpgYGANCg0KDQpDb2x1bW4gTGF5b3V0DQpgYGB7cn0NCmJvZHkgPC0gZGFzaGJvYXJkQm9keSgNCiAgICBmbHVpZFJvdygNCiAgICAjICAgQ29sdW1uIDENCiAgICAgIGNvbHVtbih3aWR0aCA9IDYsDQogICAgICBpbmZvQm94KA0KICAgICAgICB3aWR0aCA9IE5VTEwsICMgVGhlIHdpZHRoIG11c3QgYmUgIk5VTEwiIHdoZW4gdXNpbmcgYSBjb2x1bW4gbGF5b3V0DQogICAgICAgIHRpdGxlID0gIlJlZ3VsYXIgQm94LCBDb2x1bW4gMSIsDQogICAgICAgICJUZXh0IGluc2lkZSBvZiBib3giDQogICAgICAgICApICAgICAgDQogICApLA0KICBjb2x1bW4od2lkdGggPSA2LA0KICAgICMgICBDb2x1bW4gMg0KICAgICAgaW5mb0JveCgNCiAgICAgICAgd2lkdGggPSBOVUxMLCAjIFRoZSB3aWR0aCBtdXN0IGJlICJOVUxMIiB3aGVuIHVzaW5nIGEgY29sdW1uIGxheW91dA0KICAgICAgICB0aXRsZSA9ICJSZWd1bGFyIEJveCwgQ29sdW1uIDIiLA0KICAgICAgICAiVGV4dCBpbnNpZGUgb2YgYm94Ig0KICAgICAgICAgKSAgICAgIA0KICAgKQ0KKQ0KKQ0KdWkgPC0gZGFzaGJvYXJkUGFnZShoZWFkZXIgPSBkYXNoYm9hcmRIZWFkZXIoKSwNCiAgICAgICAgICAgICAgICAgICAgc2lkZWJhciA9IGRhc2hib2FyZFNpZGViYXIoKSwNCiAgICAgICAgICAgICAgICAgICAgYm9keSA9IGJvZHkNCiAgICAgICAgICAgICAgICAgICAgKQ0KDQpzaGlueUFwcCh1aSwgc2VydmVyKQ0KYGBgDQoNCg0KIyMjIE1peCBvZiBDb2x1bW4gYW5kIFJvdyBMYXlvdXQNCk5vdGU6DQpUbyBjcmVhdGUgYSBuZXcgcm93LCB5b3UgY2FsbCBhbm90aGVyIGZsdWlkUm93KCkgZnVuY3Rpb24uIA0KYGBge3J9DQpib2R5IDwtIGRhc2hib2FyZEJvZHkoDQogICAgZmx1aWRSb3coDQogICAgIyAgIFJvdyAxDQogICAgICBib3goDQogICAgICAgIHdpZHRoID0gMTIsICMgVGhlIHdpZHRoIG11c3QgYmUgIk5VTEwiIHdoZW4gdXNpbmcgYSBjb2x1bW4gbGF5b3V0DQogICAgICAgIHRpdGxlID0gIlJlZ3VsYXIgQm94LCBSb3cgMSIsDQogICAgICAgICJUZXh0IGluc2lkZSBvZiBib3giDQogICAgICAgICApLA0KICAgICksDQogIGZsdWlkUm93KA0KICAgIGNvbHVtbih3aWR0aCA9IDYsDQogICAgIyAgIENvbHVtbiAyDQogICAgICBpbmZvQm94KA0KICAgICAgICB3aWR0aCA9IE5VTEwsICMgVGhlIHdpZHRoIG11c3QgYmUgIk5VTEwiIHdoZW4gdXNpbmcgYSBjb2x1bW4gbGF5b3V0DQogICAgICAgIHRpdGxlID0gIlJlZ3VsYXIgQm94LCBSb3cgMiwgQ29sdW1uIDEiLA0KICAgICAgICBzdWJ0aXRsZSA9ICJUZXh0IGluc2lkZSBvZiBib3giDQogICAgICAgICApDQogICAgKSwNCiAgICBjb2x1bW4od2lkdGggPSA2LA0KICAgICAgaW5mb0JveCgNCiAgICAgICAgd2lkdGggPSBOVUxMLA0KICAgICAgICB0aXRsZSA9ICJSZWd1bGFyIEJveCwgUm93IDIsIENvbHVtbiAyIiwNCiAgICAgICAgc3VidGl0bGUgPSAiVGV4dCBpbnNpZGUgb2YgYm94Ig0KICAgICAgKQ0KICAgICkNCiAgKQ0KKQ0KDQp1aSA8LSBkYXNoYm9hcmRQYWdlKGhlYWRlciA9IGRhc2hib2FyZEhlYWRlcigpLA0KICAgICAgICAgICAgICAgICAgICBzaWRlYmFyID0gZGFzaGJvYXJkU2lkZWJhcigpLA0KICAgICAgICAgICAgICAgICAgICBib2R5ID0gYm9keQ0KICAgICAgICAgICAgICAgICAgICApDQoNCnNoaW55QXBwKHVpLCBzZXJ2ZXIpDQpgYGANCg0KDQojIEZsZXhkYXNoYm9hcmQNCg0KRmxleGRhc2hib2FyZCBpcyBhIHNpbWlsYXIgZGFzaGJvYXJkIHN5c3RlbSBhcyBzaGlueS4gQSBmbGV4ZGFzaGJvYXJkIGlzIGZpbGxlZCB3aXRoIGNoYXJ0cy4gVG8gY3JlYXRlIGEgZmxleGRhc2hib2FyZCwgeW91IHdpbGwgZmlyc3QgbmVlZCB0byBhZGp1c3QgdGhlIFlBTUwgaGVhZGVyLg0KDQp0aXRsZTogInRpdGxlIG9mIGRvY3VtZW50Ig0Kb3V0cHV0OiANCiAgZmxleGRhc2hib2FyZDo6ZmxleF9kYXNoYm9hcmQNCiAgDQpOb3cgeW91ciBSbWFya2Rvd24gZmlsZSB3aWxsIGJlIGludGVycHJldGVkIGFzIGEgZmxleGRhc2hib2FyZCBmaWxlLg0KDQpUaGUgZmxleGRhc2hib2FyZCBkZWZhdWx0IGxheW91dCBpcyBpbiBjb2x1bW5zLiBUbyBzZXBhcmF0ZSB0aGUgY29sdW1ucywgeW91IHdpbGwgdXNlIHRoZSBmb2xsb3dpbmcgc3ludGF4Og0KDQpgYGB7cn0NCmxpYnJhcnkoZmxleGRhc2hib2FyZCkNCmBgYA0KDQpDb2x1bW4NCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMjIENoYXJ0IEENCmBgYHtyfQ0KDQpgYGANCg0KQ29sdW1uDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyMgQ2hhcnQgQg0KYGBge3J9DQoNCmBgYA0KDQojIyBDaGFydCBDDQpgYGB7cn0NCg0KYGBgDQoNCg0KDQoNCg0KDQo=